#include "app_bt.h"
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include "log.h"
#include "app_serial.h"
#include <termios.h>


/**
 * 对设备模块进行蓝牙配置
 * 1 设置设备的蓝牙默认配置 包括蓝牙名称、蓝牙a网络id ，蓝牙的短地址，波特率
 * 2 将蓝牙数据的预处理方法装配给 设备模块
 */
int app_bt_init(device_t *device)
{
    // 1 设置设备的蓝牙默认配置 包括蓝牙名称、蓝牙a网络id ，蓝牙的短地址，波特率
    app_bt_default_config(device);
    // 2 将蓝牙数据的预处理方法装配给 设备模块
    device->pre_write = app_bt_pre_write;
    device->post_read = app_bt_post_read;
    return 0;
}

/**
 *
  把字节数组转换为蓝牙数据
   * 准备向设备写前处理数据来满足蓝牙发送数据的要求
 * 当前data: conn_type id_len msg_len id msg (01 02 03 ff ff 11 22 33)
 * 蓝牙发送数据格式:  41 54 2b 4d 45 53 48 00 6f 6f 45 46 0d 0a
  示例：41 54 2b 4d 45 53 48 00 ff ff 41 42 43 0d 0a
        41 54 2b 4d 45 53 48 00： AT+MESH（固定头部）
        ff ff: 对端的MADDR（如果是FFFF代表群发）
        11 22 33: 要发送的数据（不超过12字节）
        0d 0a：\r\n（固定结尾）
*/

int app_bt_pre_write(char *write_data, int write_data_size)
{
    char tmp_data_buff[100];
    memcpy(tmp_data_buff, "AT+MESH", 8);

    // 取发送数据的帧头 id 长度  msg长度
    int id_len = write_data[1];
    int msg_len = write_data[2];

    memcpy(tmp_data_buff + 8, write_data + 3, id_len + msg_len); // a拷贝payload

    memcpy(tmp_data_buff + 8 + id_len + msg_len, "\r\n", 2); // 补帧尾

    int data_len = 8 + id_len + msg_len + 2; // 计算新长度=8+id+msg+2

    memcpy(write_data, tmp_data_buff, data_len); // 把转换后的新数据覆盖到原始数据上

    return data_len;
}

/**
 *  读后预处理
 *
 * 读取蓝牙中的数据  转换为 字节数组
 *
 * 从设备读取数据后处理数据来满足网关应用的要求
 * 接收方得到数据1（4）：ok\r\n
 * 接收方得到数据2（3 + [2]）：f1 dd 07 23 23 ff ff 41 42 43
    f1 dd : 固定的头部
    07： 之后数据的长度（5-16之间）
    23 23：对端（发送方）的MADDR
    ff ff: 我的MADDR或ffff(群发)
    41 42 43：发送的数据
 * 处理后的数据格式：conn_type id_len msg_len id msg

 *   0 准备工作： 准备一个缓冲区用来攒数据
     1 把刚刚读到数据攒入缓冲区
     接下来都是在判断缓冲区是否i已经收集一帧完整数据
     2 判断基本长度  8个字节= 包括2帧头 1长度 2对端d地址 2我方地址 至少1个字节的内容
     3 判断是否有帧头 f1 dd  把帧头之前的数据全部清掉
     4 再判断数据长度是否大于等于缓冲区长度
     5  如果大于 则 把一帧数据提取出来，从缓冲区删除该数据，减少长度
     6  否则 返回 继续攒数据
 */

// 缓冲区
static char data_buff[100];
static int data_buff_len = 0;
static char data_header[2] = {0xf1, 0xdd};

// 清理指定长度数据
static void clear_data_buff(int clear_len)
{
    memmove(data_buff, data_buff + clear_len, data_buff_len - clear_len);
    data_buff_len -= clear_len;
}


int app_bt_post_read(char *read_data, int read_data_size)
{
    //  1 把刚刚读到数据攒入缓冲区
    memcpy(data_buff + data_buff_len, read_data, read_data_size);
    data_buff_len += read_data_size;
    // 2 判断基本长度  8个字节= 包括2帧头 1长度 2对端d地址 2我方地址 至少1个字节的内容
    if (data_buff_len < 8)
    {
        return 0;
    }
    // 3 判断是否有帧头 f1 dd  把帧头之前的数据全部清掉
    for (size_t i = 0; i < data_buff_len; i++)
    {
        if (data_buff[i] == data_header[0] && data_buff[i + 1] == data_header[1])
        { // 出现帧头
            // 把帧头之前的数据全部清掉
            clear_data_buff(i);
            // 判断数据长度是否大于等于8
            if (data_buff_len >= 8)
            {
                int payload_len = data_buff[2];
                if (data_buff_len >= 3 + payload_len)
                { // 如果当前缓冲区长度大于等于 3+数据payload长度  说明有一帧完整数据
                    // 如果大于 则 把一帧数据提取出来，从缓冲区删除该数据，减少长度
                    // 转换 01 id_len msg_len id msg

                    read_data[0] = CONNECT_TYPE_BT;                                   // 蓝牙
                    read_data[1] = 2;                                      // id_len
                    read_data[2] = payload_len - 4;                        // msg_len = payload_len-2个地址长度
                    memcpy(read_data + 3, data_buff + 3, 2);               // id 对端的地址 2个字节
                    memcpy(read_data + 5, data_buff + 7, payload_len - 4); // msg

                    clear_data_buff(3 + payload_len); // 清理
                    // 5=conn_type 1+id_len 1+msg_len 1 +id 2
                    // payload_len-4=msglen
                    int real_read_data_len = 5 + payload_len - 4; // 最终数据长度
                    return real_read_data_len;
                }
            }
        }
    }
    return 0;
}

/**
 *  读后预处理
 */
int app_bt_post_read(char *read_data, int read_data_size);

/**
 * 蓝牙状态测试 AT\r\n
 * write(fd,"AT\r\n")
 */
int app_bt_status(device_t *devive)
{
    write(devive->fd, "AT\r\n", 4);
    if (waitAck(devive) == 0)
    {
        log_info("蓝牙芯片测试通过");
        return 0;
    }
    else
    {
        log_error("蓝牙芯片测试失败");
        return -1;
    }
}

/**
 * 接收响应数据
 * read(fd,"OK\r\n")
 */
int waitAck(device_t *devive)
{
    usleep(50 * 1000);
    char ackChar[4];
    ssize_t read_size = read(devive->fd, ackChar, 4);
    if (memcmp(ackChar, "OK\r\n", 4) == 0)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

/**
 * 重启l蓝牙芯片
 * write(fd,"AT+RESET\r\n")
 */
int app_bt_reset(device_t *devive)
{
    write(devive->fd, "AT+RESET\r\n", 10);
    return 0;
}

/**
 * 设置蓝牙波特率
 * write(fd,"AT+BAUD?\r\n")
 */
int app_bt_set_baudrate(device_t *devive, BT_BAUD_RATE baudrate)
{
    char cmd[100];
    sprintf(cmd, "AT+BAUD%c\r\n", baudrate);
    write(devive->fd, cmd, strlen(cmd));
    if (waitAck(devive) == 0)
    {
        log_info("波特率设置成功:%c", baudrate);
        return 0;
    }
    else
    {
        log_error("波特率设置设置:%c", baudrate);
        return -1;
    }
    return 0;
}

/**
 * 设置网络广播名
 * write(fd,"AT+NAME?\r\n")
 */
int app_bt_set_name(device_t *device, char *name)
{
    char cmd[100];
    sprintf(cmd, "AT+NAME%s\r\n", name);
    write(device->fd, cmd, strlen(cmd));
    return waitAck( device);
}

/**
 * 设置NETID
 * write(fd,"AT+NETID?\r\n")
 */
int app_bt_set_netid(device_t *device, char *netid)
{
    char cmd[100];
    sprintf(cmd,"AT+NETID%s\r\n",netid);
    log_info("netida长度 :%d",strlen(cmd));
    log_info("netida长度 :%s",cmd);
    write(device->fd,cmd,strlen(cmd));

    return waitAck( device);
}

/**
 * 设置短地址
 * write(fd,"AT+MADDR?\r\n")
 */
int app_bt_set_maddr(device_t *device, char *maddr)
{
    char cmd[100];
    sprintf(cmd, "AT+MADDR%s\r\n", maddr);
    write(device->fd, cmd, strlen(cmd));
    return waitAck( device);
}

/**
 * 获取蓝牙默认配置信息
 */
int app_bt_default_config(device_t *device)
{ // 0 因为要做测试  设置串口非阻塞模式
    app_serial_set_blocking(device, 0);
    tcflush(device->fd, TCIOFLUSH);
    // 1 先做测试
    int ret = app_bt_status(device);
    // 看看能不能主控芯片和蓝牙连通  （假设主控芯片为115200）
    if (ret != 0)
    {
        // 2  测试不通过 ： 协调波特率
        // 2.1  把主控芯片的串口波特率设置为9600
        app_serial_set_baudrate(device, BR_9600);
        tcflush(device->fd, TCIOFLUSH);
        // 2.2  再测试蓝牙芯片如果可以联通
        int ret2 = app_bt_status(device);
        if (ret2 != 0)
        {
            log_error("蓝牙芯片波特率依然不通过");
            return -1;
        }
        // 2.3  给蓝牙芯片设置波特率为115200
        ret = app_bt_set_baudrate(device, BT_BAUD_115200);
        if (ret != 0)
        {
            return -1;
        }
        // // 2.4  重启蓝牙芯片
        app_bt_reset(device);
        // // 2.5  等2秒
        sleep(2);
        // 2.6  把主控芯片的串口波特率设置会115200
        app_serial_set_baudrate(device, BR_115200);
        tcflush(device->fd, TCIOFLUSH);
        // 2.7  再测试蓝牙芯片是否可以联通
        ret = app_bt_status(device);
        if (ret != 0)
        {
            log_error("蓝牙芯片协调波特率失败");
        }
    }
    // 3  测试通过
    // 3.1 设置其他项 广播名 netid maddr
    app_bt_set_name(device, "atguigu");
    app_bt_set_netid(device, "1234"); // 1234 老师专用
    app_bt_set_maddr(device, "0071");

    // 4  恢复串口为阻塞模式
    app_serial_set_blocking(device, 1);
    tcflush(device->fd, TCIOFLUSH);

    log_info("蓝牙默认配置设置成功");
    return 0;
}